"""
Human-in-the-loop（人机交互）示例

主要使用场景：
1. 审查工具使用：人类可以在工具执行前审查、编辑或批准LLM请求的工具调用
2. 验证LLM输出：人类可以审查、编辑或批准LLM生成的内容
3. 提供上下文：使LLM能够明确请求人类输入以进行澄清或提供额外细节，或支持多轮对话

interrupt 函数：用于在工作流的特定节点前暂停执行，等待人类干预
"""
from typing import TypedDict

from langgraph.checkpoint.memory import MemorySaver
from langgraph.constants import START, END
from langgraph.graph import StateGraph


# 定义状态类，包含输入字符串
class State(TypedDict):
    input: str


def step1(state: State):
    """第一步：处理初始输入"""
    print("----Step 1----")
    # 这里可以添加实际的处理逻辑
    # 例如：预处理用户输入、调用LLM等
    pass


def step2(state: State):
    """第二步：进一步处理数据"""
    print("----Step 2----")
    # 这里可以添加中间处理逻辑
    # 例如：数据转换、分析等
    pass


def step3(state: State):
    """第三步：最终处理（需要人工审批的步骤）"""
    print("----Step 3----")
    # 这里通常是关键操作，需要人类审查
    # 例如：发送邮件、执行数据库操作、生成重要报告等
    pass


# ========== 构建工作流图 ==========

# 创建状态图构建器
builder = StateGraph(State)

# 添加三个处理节点
builder.add_node("step1", step1)  # 第一步处理节点
builder.add_node("step2", step2)  # 第二步处理节点
builder.add_node("step3", step3)  # 第三步处理节点（需要人工审批）

# 构建线性工作流：START -> step1 -> step2 -> step3 -> END
builder.add_edge(START, "step1")      # 从开始到第一步
builder.add_edge("step1", "step2")    # 从第一步到第二步
builder.add_edge("step2", "step3")    # 从第二步到第三步
builder.add_edge("step3", END)        # 从第三步到结束

# 创建内存检查点保存器，用于保存工作流状态
memory = MemorySaver()

# 编译工作流，并在 step3 节点前设置中断点
# interrupt_before 参数指定在哪些节点执行前暂停，等待人类干预
graph = builder.compile(
    checkpointer=memory,          # 使用检查点保存状态
    interrupt_before=["step3"]    # 在 step3 节点执行前中断，等待人工批准
)

# ========== 执行工作流 ==========

# 设置初始输入数据
initial_input = {"input": "你好，qdb"}

# 设置线程配置，用于标识对话会话
thread = {"configurable": {"thread_id": "7"}}

print("开始执行工作流（将在第三步前暂停）...")

# 第一次执行：从开始运行到中断点（step3之前）
for event in graph.stream(initial_input, thread, stream_mode="values"):
    print("工作流执行事件:", event)

print("\n工作流已在第三步前暂停，等待用户决策...")

# ========== 人机交互环节 ==========

# 向用户请求是否继续执行第三步
user_approval = input("你想继续执行第三步吗？（是/否）: ")

# 根据用户输入决定是否继续执行
if user_approval.lower() == "是" or user_approval.lower() == "y":
    print("用户批准，继续执行第三步...")

    # 继续执行工作流（从中断点开始）
    # 传入 None 表示继续使用之前的状态，不需要新的输入
    for event in graph.stream(None, thread, stream_mode="values"):
        print("继续执行事件:", event)

    print("工作流执行完成！")
else:
    # 用户取消执行，工作流保持在中断状态
    print("用户取消了流程执行，工作流终止于第三步前")
    # 此时工作流状态会保存在检查点中，可以在以后继续执行